<?php

namespace app\common\command;

use app\common\model\Bill;
use think\console\Command;
use think\console\Input;
use think\console\Output;
use think\Db;
use think\Exception;
use think\Queue;

class AgainOpenBill extends Command
{
    const STATUS_OPENED = 22; // 发票状态 开票失败
    const STATUS_PROCESSING = 1;//发票状态 待提交到诺诺第三方
    const BILL_TYPE = 1; //发票类型 1蓝票
    protected function configure()
    {
        $this->setName('again-open-bill');
    }

    protected function execute(Input $input, Output $output)
    {
        try{
            $list = Bill::where(['status' => self::STATUS_OPENED, 'client_status' => 0, 'bill_type' => self::BILL_TYPE])->select();
            Db::startTrans();
            foreach ($list as $value){
                // 队列推送失败时，异常会被catch，然后事务回滚
                $this->pushToQueue($value->member_id, $value->id);
                $value->status = self::STATUS_PROCESSING;
                $value->orderNo = $value->orderNo.'_'.rand(000,999);
                $value->save();
            }
            // 提交事务
            Bill::commit();

            $output->info("AgainOpendBill Successed!");
        }catch (Exception $e){
            // 回滚事务
            Bill::rollback();
            $output->error("AgainOpenBill Failed: " . $e->getMessage());
        }
    }

    /**
     * 推送任务到队列
     * @param int $memberId 会员ID
     * @param int $billId 账单ID
     * @throws Exception 如果队列推送失败且无法重试，则抛出异常
     */
    private function pushToQueue(int $memberId, int $billId)
    {
        try {
            Queue::push(\app\job\Bill::class, ['member_id' => $memberId, 'bill_id' => $billId], 'message');
        } catch (Exception $e) {
            // 如果配置了队列重试机制，则这里可能不需要抛出异常；
            // 但根据题目要求，如果遇到异常需要提醒用户，因此这里抛出异常以触发catch块处理
            throw new Exception("Failed to push bill processing job to queue for bill ID: $billId");
        }
    }


}
